﻿/*
    Bisounours Party Updater - Update Source Engine Mods
    Copyright (C) 2012  Louis «Orygin» Geuten and Hekar Khani

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
   
    Bisounours Party Updater  
    Copyright (C) 2012  Louis «Orygin» Geuten and Hekar Khani
    This program comes with ABSOLUTELY NO WARRANTY;
    This is free software, and you are welcome to redistribute it
    under certain conditions;
*/
using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Threading;
using System.Diagnostics;
using System.ComponentModel;

namespace bpUpdater
{
    public partial class RootForm : Form, Logger
    {
        private string[] args;

        private bool NeedToClean;
        private string GameDir;
        private string WorkDir;

        private Configuration config;
        private Updater updater;
        private BackgroundWorker worker;

        delegate void LogLineDel(string line);

        public RootForm(string[] args)
        {
            this.args = args;
            InitializeComponent();

            worker = new BackgroundWorker();
            worker.DoWork += new DoWorkEventHandler(delegate
            {
                RetrieveAndUpdate();
            });
            worker.RunWorkerCompleted += RunWorkerCompletedEventHandler;
            worker.WorkerSupportsCancellation = true;
            
            RefreshData();
        }

        public void RefreshData()
        {
            if (args.Length == 1)
            {
                WorkDir = args[0];
            }
            else
            {
                WorkDir = Application.StartupPath;
            }

            // Make sure the workdir always ends with the directory separator
            if (!WorkDir.EndsWith(Path.DirectorySeparatorChar.ToString()))
            {
                WorkDir += Path.DirectorySeparatorChar;
            }

            GameDir = WorkDir + "version";

            config = new Configuration();
            switch (config["method"])
            {
                case BuUpdater.Method:
                    updater = new BuUpdater(GameDir, config["lastVersionUrl"]);
                    break;
                case SvnUpdater.Method:
                    // Temp for testing
                    //GameDir = @"C:\Program Files\Steam\steamapps\sourcemods\luminousforts\";
                    GameDir = @"C:\Users\hekar\Desktop\luminousforts";
                    updater = new SvnUpdater(GameDir, config["lastVersionUrl"]);
                    break;
                default:
                    throw new ArgumentException(
                        String.Format("app.config key 'method': {0} not found", config["method"]));
            }

            if (updater.InstallRequired)
            {
                updateStripButton.Text = "Start Install";
            }
            else
            {
                updateStripButton.Text = "Start Update";
            }

            logBox.Text = "";
            LogLine("Updater started.");
            LogLine("Loading local version file.");

            string method = config["method"];
            if (method == "http")
            {
                if (!File.Exists(GameDir))
                {
                    MessageBox.Show("Local Version not found\n Reinstalling the game will correct this problem", "Critical Error");
                }
            }

            string localVersion = updater.LocalVersion.ToString();
            LogLine("Current version is " + localVersion);
            LogLine("Finding latest version of mod...");
            string remoteVersion = updater.ServerVersion.ToString();
            LogLine(String.Format("Latest version is {0}", remoteVersion));

            m_lLocalVersion.Text = localVersion;
            m_lNewVersion.Text = remoteVersion;

            if (updater.Iterations < 1)
            {
                LogLine("No new update needed");
            }
            else
            {
                LogLine(updater.Iterations + " new updates available");
            }

            if (!updater.InstallRequired && !updater.UpdateRequired)
            {
                updateStripButton.Text = "Force Update";
            }

            NeedToClean = Cleanup.Checked;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Text = String.Format(config["windowCaption"], config["modName"]);
            MaximizeBox = false;
        }

        void FinishedUpdates()
        {
            m_lLocalVersion.Text = updater.ServerVersion.ToString();

            DialogResult res = MessageBox.Show("Your game is now up to date. Open changelog file ?",
                "Done", MessageBoxButtons.YesNo);

            if (res == DialogResult.Yes)
            {
                ProcessStartInfo n = new ProcessStartInfo();
                n.FileName = "notepad";
                n.Arguments = @"CHANGELOG.TXT";
                n.WorkingDirectory = GameDir;
                Process x = Process.Start(n);
            }
        }

        public void LogLine(string text)
        {
            try
            {
                logBox.Text += text + "\n";
            }
            catch (InvalidOperationException)
            {
                this.BeginInvoke(new LogLineDel(LogLine), text);
            }
        }

        void RetrieveAndUpdate()
        {
            Invoke(new MethodInvoker(() => { 
                progressBarStatus.Visible = true; 
            }));
            LogLine("Starting the update");
            updater.RetrieveAndUpdate(NeedToClean, config["updateUrl"], GameDir, this);
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var about = new AboutDialog();
            about.ShowDialog();
        }

        private void updateStripButton_Click(object sender, EventArgs e)
        {
            worker.RunWorkerAsync();
            updateStripButton.Enabled = false;
        }

        private void refreshStripButton_Click(object sender, EventArgs e)
        {
            RefreshData();
        }

        private void RunWorkerCompletedEventHandler(object sender, RunWorkerCompletedEventArgs e)
        {
            if(e.Cancelled)
            {
                LogLine("Update Cancelled.");
                updater.CleanUp();
            }

            FinishedUpdates();
            progressBarStatus.Visible = false;
            updateStripButton.Enabled = true;
        }

        private void uninstallModToolStripMenuItem_Click(object sender, EventArgs e)
        {
            updater.DeleteFiles();
        }
    }
}
